/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.service.impl;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import com.xy.biz.base.client.DictClient;
import com.xy.tool.constant.DocumentExtension;
import com.xy.tool.constant.QrCodeUrlConstant;
import com.xy.tool.gid.service.GidService;
import com.xy.tool.minio.util.LedgerTemplateUtils;
import com.xy.tool.minio.util.MinioUtil;
import com.xy.tool.util.QRCodeGenerateUtils;
import com.xy.tool.context.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xy.lang.domain.Result;
import com.xy.biz.base.domain.bo.QrCodeBO;
import com.xy.biz.base.domain.query.QrCodeQuery;
import com.xy.biz.base.service.QrCodeService;
import com.xy.biz.base.manager.QrCodeManager;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 *
 * @author zgy
 * @date 2021-8-11
 */
@Slf4j
@Service
public class QrCodeServiceImpl implements QrCodeService {

    @Autowired
    private QrCodeManager qrCodeManager;
    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private GidService gidService;

    @Override
    public Result<?> saveQrCode(QrCodeBO qrCodeBO) {
        Result result;
        if ((result = isExist(qrCodeBO)).wasFailure()) {
            return result;
        }
        buildQrCode(qrCodeBO);
        QrCodeBO qrCode = qrCodeManager.saveQrCode(qrCodeBO);
        if (!Objects.isNull(qrCode)) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }


    private void buildQrCode(QrCodeBO qrCodeBO) {
        qrCodeBO.setCreateTime(LocalDateTime.now());
        qrCodeBO.setTenantId(UserContextHolder.getTenantId());
        qrCodeBO.setCreateUserId(UserContextHolder.getUserId());
        qrCodeBO.setCreateUserName(UserContextHolder.getUserName());
        long generate = gidService.generate();
        String qrCodeName = generate + DocumentExtension.PNG;
        try {
            //根据文本生成二维码
            byte[] bytes = QRCodeGenerateUtils.generate(qrCodeBO.getUrl(), qrCodeBO.getWidth(), qrCodeBO.getHeight());
            minioUtil.uploadFile(new ByteArrayInputStream(bytes), qrCodeName, MinioUtil.qrCodeImage);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        qrCodeBO.setQrCodePath(qrCodeName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteQrCode(Long qrCodeId) {
        QrCodeBO qrCode = qrCodeManager.getQrCode(qrCodeId);
        if (Objects.isNull(qrCode)) {
            return Result.ofNotFound("无此数据！");
        }
        int affectedRows = qrCodeManager.deleteQrCode(qrCodeId);
        if (affectedRows > 0) {
            try {
                minioUtil.removeObject(MinioUtil.qrCodeImage, qrCode.getQrCodePath());
            } catch (Exception e) {
                log.error(e.getMessage());
            }
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    /**
     * 判断是否存在相同分类下的文本
     *
     * @param qrCodeBO
     */
    @Override
    public Result<?> isExist(QrCodeBO qrCodeBO) {
        int exist = qrCodeManager.isExist(qrCodeBO);
        if (exist > 0) {
            return Result.fail("", "已存在相同分类下二维码文本！");
        }
        return Result.success();
    }

    @Override
    public QrCodeBO getQrCode(Long qrCodeId) {
        QrCodeBO qrCode = qrCodeManager.getQrCode(qrCodeId);
        if (!Objects.isNull(qrCode)) {
            try {
                InputStream qrCodeImage = minioUtil.getObject(MinioUtil.qrCodeImage, qrCode.getQrCodePath());
                qrCode.setQrCode(QRCodeGenerateUtils.readStream(qrCodeImage));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        return qrCode;
    }

    /**
     * 查找一个!
     * 不存在则自动生成
     *
     * @param qrCodeBO
     * @return
     */
    @Override
    public QrCodeBO getQrCodeByText(QrCodeBO qrCodeBO) {
        QrCodeBO existedQrCode = qrCodeManager.getQrCodeByText(qrCodeBO);
        if (Objects.isNull(existedQrCode)) {
            buildQrCode(qrCodeBO);
            existedQrCode = qrCodeManager.saveQrCode(qrCodeBO);
        }
        try {
            InputStream qrCodeImage = minioUtil.getObject(MinioUtil.qrCodeImage, existedQrCode.getQrCodePath());
            existedQrCode.setQrCode(QRCodeGenerateUtils.readStream(qrCodeImage));
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return existedQrCode;
    }

    @Override
    public List<QrCodeBO> listQrCodeById(Collection<Long> collection) {
        List<QrCodeBO> qrCodeBOS = qrCodeManager.listQrCodeById(collection);
        for (QrCodeBO qrCodeBO : qrCodeBOS) {
            try {
                InputStream qrCodeImage = minioUtil.getObject(MinioUtil.qrCodeImage, qrCodeBO.getQrCodePath());
                qrCodeBO.setQrCode(QRCodeGenerateUtils.readStream(qrCodeImage));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        return qrCodeBOS;
    }

    @Override
    public List<QrCodeBO> listQrCode(QrCodeQuery query) {
        List<QrCodeBO> qrCodeBOS = qrCodeManager.listQrCode(query);
        for (QrCodeBO qrCodeBO : qrCodeBOS) {
            try {
                InputStream qrCodeImage = minioUtil.getObject(MinioUtil.qrCodeImage, qrCodeBO.getQrCodePath());
                qrCodeBO.setQrCode(QRCodeGenerateUtils.readStream(qrCodeImage));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        return qrCodeBOS;
    }

    @Override
    public int countQrCode(QrCodeQuery query) {
        return qrCodeManager.countQrCode(query);
    }

}
